package test.my.com.myapplicationtest.RangeSliderBar;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.NinePatch;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import test.my.com.myapplicationtest.R;


/**
 * Author : Cooper
 * Time : 2017/7/5  15:51
 * Description : 范围滑动杆
 */

public class RangeSliderBar extends View {

    private Context mContext;
    private Paint mPaint;

    private int mSliderBarBg;
    private Bitmap mSliderBarBgBitmap;
    private NinePatch mBarBgpatch;
    private Rect mBarBgRect = new Rect();

    private int mSelectedPartBg;
    private Bitmap mSelectedPartBgBitmap;
    private NinePatch mSelectedPartBgpatch;
    private Rect mSelectedPartBgRect = new Rect();

    private int mSliderIcon;
    private Bitmap mSliderIconBitmap;
    private Rect mSliderIconRect = new Rect();
    private Rect mDirSliderIconRect = new Rect();

    private int mScaleIcon;
    private Bitmap mScaleIconBitmap;
    private Rect mScaleIconRect = new Rect();
    private Rect mDirScaleIconRect = new Rect();

    private float mDownX;
    private float mDownY;
    private float mRange = 40; //扩大滑动bar点击范围

    private int mWidth = 200;
    private int mHeight = 20;

    private int mMoveDistance; // 相对于进度条中的滑动距离
    private int mScaleDistance; //刻度距离
    private boolean isTouchSlider; //是否点击到拖动bar
    private float mMoveX; //滑动是的坐标X

    private int mActualRange; //实际总范围

    private SliderDragProgressCallBack mSliderDragProgressCallBack;

    public void setSliderDragProgressCallBack(SliderDragProgressCallBack sliderDragProgressCallBack) {
        this.mSliderDragProgressCallBack = sliderDragProgressCallBack;
    }

    public RangeSliderBar(Context context) {
        super(context);
    }

    public RangeSliderBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RangeSliderBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RangeSliderBar, defStyleAttr, 0);
        mSliderBarBg = typedArray.getResourceId(R.styleable.RangeSliderBar_sliderBarBg, R.drawable.dingqi_gdt_bj);
        mSliderIcon = typedArray.getResourceId(R.styleable.RangeSliderBar_sliderIcon, R.drawable.dingqi_gdtan);
        mSelectedPartBg = typedArray.getResourceId(R.styleable.RangeSliderBar_selectedPartBg, R.drawable.dingqi_gdtjd);
        mScaleIcon = typedArray.getResourceId(R.styleable.RangeSliderBar_scaleIcon, R.drawable.dingqi_gdtjd_a);
        mActualRange = typedArray.getInteger(R.styleable.RangeSliderBar_actualRange, 100);
        typedArray.recycle();

        init(context);
    }

    private void init(Context context) {
        this.mContext = context;
        mPaint = new Paint();
        mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        mPaint.setFilterBitmap(true);
        mPaint.setDither(true);

        mSliderBarBgBitmap = BitmapFactory.decodeResource(getResources(), mSliderBarBg);
        mBarBgpatch = new NinePatch(mSliderBarBgBitmap, mSliderBarBgBitmap.getNinePatchChunk(), null);

        mSelectedPartBgBitmap = BitmapFactory.decodeResource(getResources(), mSelectedPartBg);
        mSelectedPartBgpatch = new NinePatch(mSelectedPartBgBitmap, mSelectedPartBgBitmap.getNinePatchChunk(), null);

        mSliderIconBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(mSliderIcon))
                .getBitmap();
        mSliderIconRect.set(0, 0, mSliderIconBitmap.getWidth(), mSliderIconBitmap.getHeight());

        mScaleIconBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(mScaleIcon))
                .getBitmap();
        mScaleIconRect.set(0, 0, mScaleIconBitmap.getWidth(), mScaleIconBitmap.getHeight());

        mWidth = mSliderIconBitmap.getWidth() + mSliderBarBgBitmap.getWidth();
        mHeight = mSliderIconBitmap.getHeight();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
        mDirSliderIconRect.set(mMoveDistance, mHeight / 2 - mSliderIconBitmap.getHeight() / 2
                , mSliderIconBitmap.getWidth() + mMoveDistance, mHeight / 2 + mSliderIconBitmap.getHeight() / 2);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        drawBarBg(canvas);
        drawSelectedPart(canvas);
        drawScaleIcon(canvas);
        drawSliderIcon(canvas);
    }

    /**
     * 画滑动条背景
     *
     * @param canvas
     */
    private void drawBarBg(Canvas canvas) {
        mBarBgRect.set(mSliderIconBitmap.getWidth() / 2, mHeight / 2 - mSliderBarBgBitmap.getHeight() / 2
                , mWidth - mSliderIconBitmap.getWidth() / 2, mHeight / 2 + mSliderBarBgBitmap.getHeight() / 2);
        mBarBgpatch.draw(canvas, mBarBgRect);
    }

    /**
     * 画滑动块
     *
     * @param canvas
     */
    private void drawSliderIcon(Canvas canvas) {
        canvas.drawBitmap(mSliderIconBitmap, mSliderIconRect, mDirSliderIconRect, mPaint);
    }

    /**
     * 画刻度
     *
     * @param canvas
     */
    private void drawScaleIcon(Canvas canvas) {
        mScaleDistance = mBarBgRect.width() / 4;
        for (int i = 1; i < 4; i++) {
            mDirScaleIconRect.set(mSliderIconBitmap.getWidth() / 2 + i * mScaleDistance, mHeight / 2 - mScaleIconBitmap.getHeight() / 2
                    , mSliderIconBitmap.getWidth() / 2 + i * mScaleDistance + mScaleIconBitmap.getWidth(), mHeight / 2 + mScaleIconBitmap.getHeight() / 2);
            canvas.drawBitmap(mScaleIconBitmap, mScaleIconRect, mDirScaleIconRect, mPaint);
        }
    }

    /**
     * 画滑动选择后的背景
     *
     * @param canvas
     */
    private void drawSelectedPart(Canvas canvas) {
        mSelectedPartBgRect.set(mSliderIconBitmap.getWidth() / 2, mHeight / 2 - mSliderBarBgBitmap.getHeight() / 2
                , mSliderIconBitmap.getWidth() / 2 + mMoveDistance, mHeight / 2 + mSliderBarBgBitmap.getHeight() / 2);
        mSelectedPartBgpatch.draw(canvas, mSelectedPartBgRect);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int distance = 0;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mDownX = event.getX();
                mDownY = event.getY();
                if (mDownX > mDirSliderIconRect.left - mRange && mDownX < mDirSliderIconRect.right + mRange && mDownY > mDirSliderIconRect.top - mRange && mDownY < mDirSliderIconRect.bottom + mRange) {
                    isTouchSlider = true;
                } else {
                    isTouchSlider = false;
                }
                mMoveX = mDownX;
                break;
            case MotionEvent.ACTION_MOVE:
                if (isTouchSlider) {
                    float moveX = event.getX();
                    distance = (int) (moveX - mMoveX);
                    mDirSliderIconRect.left += distance/*+mSliderIconBitmap.getWidth() / 2*/;
                    mDirSliderIconRect.right += distance/*+mSliderIconBitmap.getWidth()*/;
                    if (mDirSliderIconRect.left < 0) { // 解决滑动到最左边后，滑块停止在最左边
                        mDirSliderIconRect.left = 0;
                        mDirSliderIconRect.right = mSliderIconBitmap.getWidth();
                    }
                    if (mDirSliderIconRect.right > mBarBgRect.right + mSliderIconBitmap.getWidth() / 2) { // 解决滑动到最右边后，滑块停止在最右边
                        mDirSliderIconRect.left = mBarBgRect.right - mSliderIconBitmap.getWidth() / 2;
                        mDirSliderIconRect.right = mBarBgRect.right + mSliderIconBitmap.getWidth() / 2;
                    }
                    mMoveDistance = mDirSliderIconRect.left; //滑动距离
                    if (mSliderDragProgressCallBack != null) {
                        mSliderDragProgressCallBack.dragProgress(mMoveDistance * mActualRange / mBarBgRect.width());
                    }
                    invalidate();
                    mMoveX = moveX;
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                upAdsorb();
                isTouchSlider = false;
                break;
        }
        return true;
    }

    /**
     * 抬起吸附到指定位置逻辑
     */
    private void upAdsorb() {
        int distanceAbs = mBarBgRect.width();
        int direction = 0;
        for (int i = 0; i <= 4; i++) {
            int scale = i * mScaleDistance;
            if (Math.abs(mMoveDistance - scale) < distanceAbs) {
                distanceAbs = Math.abs(mMoveDistance - scale);
                direction = scale;
            }
        }
        direction += mSliderIconBitmap.getWidth() / 2;
        mDirSliderIconRect.left = direction - mSliderIconBitmap.getWidth() / 2;
        mDirSliderIconRect.right = direction + mSliderIconBitmap.getWidth() / 2;
        mMoveDistance = mDirSliderIconRect.left; //滑动距离
        invalidate();
        if (mSliderDragProgressCallBack != null) {
            mSliderDragProgressCallBack.dragProgress(mMoveDistance * mActualRange / mBarBgRect.width());
        }
    }

    private int measureWidth(int widthMeasureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = mWidth;
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        this.mWidth = result;
        return result;
    }

    private int measureHeight(int heightMeasureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(heightMeasureSpec);
        int specSize = MeasureSpec.getSize(heightMeasureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = mHeight;
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        this.mHeight = result;
        return result;
    }

    public interface SliderDragProgressCallBack {
        void dragProgress(int progress);
    }
}
